package demo.builder;


import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author : feixiang.li
 * @since : 2025-09-17 21:38
 */
public class SQL {


    public static SQLBuilder build(SqlType sqlType) {
        return new SQLBuilder(sqlType);
    }

    public static SelectBuilder select() {
        return new SelectBuilder();
    }

    public static TableStage update() {
        return new UpdateBuilder();
    }

    public static InsertBuilder insert() {
        return new InsertBuilder();
    }


    interface TableStage {
        WhereStage table(String table);
    }

    interface SetStage {
        SetStage setParams(String key, Object value);

        String build();
    }

    interface WhereStage {
        SetStage where(String where);
    }


    public static class UpdateBuilder implements SetStage, WhereStage, TableStage {

        String table;
        String where;
        Map<String, Object> params = new LinkedHashMap<>();

        public SetStage setParams(String key, Object value) {
            this.params.put(key, value);
            return this;
        }


        public UpdateBuilder table(String table) {
            this.table = table;
            return this;
        }


        public UpdateBuilder where(String where) {
            this.where = where;
            return this;
        }

        public String build() {
            StringBuilder sb = new StringBuilder();
            sb.append("UPDATE ").append(table).append(" SET ");
            int i = 0;
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                sb.append(entry.getKey()).append(" = ").append("'").append(entry.getValue()).append("'");
                if (i != params.entrySet().size() - 1) {
                    sb.append(",");
                }
                i++;
            }
            sb.append(" WHERE ").append(where);
            return sb.toString();
        }
    }

    public static class InsertBuilder {
        String[] columns;
        String table;
        String[] values;

        public InsertBuilder columns(String... columns) {
            this.columns = columns;
            return this;
        }

        public InsertBuilder table(String table) {
            this.table = table;
            return this;
        }

        public InsertBuilder values(String... values) {
            this.values = values;
            return this;
        }

        public String build() {
            StringBuilder sb = new StringBuilder();
            sb.append("INSERT INTO ").append(table).append(" (");
            for (int i = 0; i < columns.length; i++) {
                sb.append(columns[i]);
                if (i != columns.length - 1) {
                    sb.append(",");
                }
            }
            sb.append(") VALUES (");
            for (int i = 0; i < values.length; i++) {
                sb.append("'").append(values[i]).append("'");
                if (i != values.length - 1) {
                    sb.append(",");
                }
            }
            sb.append(")");
            return sb.toString();
        }

    }


    public static class SelectBuilder {
        String[] columns;
        String table;
        String where;

        public SelectBuilder columns(String... columns) {
            this.columns = columns;
            return this;
        }

        public SelectBuilder table(String table) {
            this.table = table;
            return this;
        }

        public SelectBuilder where(String where) {
            this.where = where;
            return this;
        }

        public String build() {
            StringBuilder sb = new StringBuilder();
            sb.append("SELECT ");
            for (int i = 0; i < columns.length; i++) {
                sb.append(columns[i]);
                if (i != columns.length - 1) {
                    sb.append(",");
                }
            }
            sb.append(" FROM ").append(table);
            if (where != null) {
                sb.append(" WHERE ").append(where);
            }
            return sb.toString();
        }
    }

    public static class SQLBuilder {
        final SqlType sqlType;
        String[] columns;
        Map<String, Object> params = new LinkedHashMap<>();
        String table;
        String where;

        public SQLBuilder columns(String... columns) {
            this.columns = columns;
            return this;
        }

        public SQLBuilder params(String key, Object value) {
            this.params.put(key, value);
            return this;
        }

        public SQLBuilder table(String table) {
            this.table = table;
            return this;
        }

        public SQLBuilder where(String where) {
            this.where = where;
            return this;
        }


        public SQLBuilder(SqlType sqlType) {
            this.sqlType = sqlType;
        }

        public String build() {
            StringBuilder sb = new StringBuilder();
            switch (sqlType) {
                case SELECT:
                    sb.append("SELECT ");
                    for (int i = 0; i < columns.length; i++) {
                        sb.append(columns[i]);
                        if (i != columns.length - 1) {
                            sb.append(",");
                        }
                    }
                    sb.append(" FROM ").append(table);
                    if (where != null) {
                        sb.append(" WHERE ").append(where);
                    }
                    break;
                case UPDATE:
                    sb.append("UPDATE ").append(table).append(" SET ");
                    int i = 0;
                    for (Map.Entry<String, Object> entry : params.entrySet()) {
                        sb.append(entry.getKey()).append(" = ").append("'").append(entry.getValue()).append("'");
                        if (i != params.entrySet().size() - 1) {
                            sb.append(",");
                        }
                        i++;
                    }
                    if (where != null) {
                        sb.append(" WHERE ").append(where);
                    }
                    break;

            }
            return sb.toString();
        }
    }

    public enum SqlType {
        SELECT, INSERT, UPDATE, DELETE
    }
}
